/*
 * TokenBucketProfiler.cc
 *
 *  Created on: 2011-04-11
 *      Author: Jagger
 */

#include "TokenBucketProfiler.h"

Define_Module(TokenBucketProfiler)

void TokenBucketProfiler::initialize()
{
	AbstractProfiler::initialize();

	tokens 				= 0;
	tokensMax			= par("tokensMax");
	tokenIncrement 		= par("tokenIncrement");
	lastTokenIncrement 	= SIMTIME_ZERO;
	lastDelayedPacket	= NULL;

	WATCH(tokens);
}

bool TokenBucketProfiler::acceptPacket(NetPacket* packet, simtime_t& delay)
{
	simtime_t currentTime = simTime();
	simtime_t timeDiff = currentTime - lastTokenIncrement;

	// Zwieksz ilosc tokenow w wiadrze jesli uplynal jakis czas.
	if(timeDiff > 0)
		tokens = std::min((int32_t)(tokens + tokenIncrement * timeDiff.dbl()), tokensMax);
	lastTokenIncrement = currentTime;

	// Zakladajac ze obliczenia dla ostatniego zakolejkowanego pakietu sa
	// poprawne mozemy bezproblemowo przeslac go dalej.
	if(packet == lastDelayedPacket)
		return true;
	else if(packet->getByteLength() <= tokens)
	{
		// Jesli dlugosc pakietu jest niewieksza od liczby tokenow to mozna go
		// przeslac dalej.
		tokens -= packet->getByteLength();
		return true;
	}
	else
	{
		// Wylicz czas po ktorym ma nastapic kolejne sprawdzenie dla tego pakietu.
		lastDelayedPacket = packet;
		delay = (double)(packet->getByteLength() - tokens) / tokenIncrement;
		tokens -= packet->getByteLength(); // Mozliwe wartosci ujemne, ale jest to akceptowalne

		return false;
	}
}
